package study.springcloud.gateway.filter.global;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import study.springcloud.gateway.support.utils.WebUtils;

import java.nio.charset.StandardCharsets;

/**
 * https://blog.csdn.net/qq_33803102/article/details/135950090
 */
@Slf4j
@Component
public class ModifyResponseBodyFilter implements GlobalFilter, Ordered {

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info(">>>>>> ModifyResponseBodyFilter");
        //
        ServerHttpResponse response = WebUtils.getServerHttpResponse(exchange);

        //
        ServerHttpResponseDecorator decorator = new ServerHttpResponseDecorator(response) {

            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                log.info(">>>>>>>>>> bbbbbbbbbbbbbbbbbbb");
                return super.writeWith(Flux.from(body).map(dataBuffer -> {
                    // 读取 body
                    byte[] content = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(content);
                   // DataBufferUtils.release(dataBuffer);

                    // 打印
                    String bodyStr = StrUtil.str(content, StandardCharsets.UTF_8);
                    log.info(">>>>>>>> {}", bodyStr);
                    // Modify the response body here
                    bodyStr = bodyStr.replace("requestId", "newValue");

                    byte[] uppedContent = bodyStr.getBytes(StandardCharsets.UTF_8);
                    getDelegate().getHeaders()
                            .setContentLength(uppedContent.length);
                    //
                    return bufferFactory().wrap(uppedContent);
                }));
            }
        };
        //
        ServerWebExchange newExchange = exchange.mutate()
                .response(decorator).build();
        //
        return chain.filter(newExchange);
    }
}
